home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Panorama / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].zip / Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].adf / PipeHandler1.2 / pipename.c < prev    next >
C/C++ Source or Header  |  1987-06-28  |  10KB  |  373 lines

  1. /****************************************************************************
  2. **  File:       pipename.c
  3. **  Program:    pipe-handler - an AmigaDOS handler for named pipes
  4. **  Version:    1.1
  5. **  Author:     Ed Puckett      qix@mit-oz
  6. **
  7. **  Copyright 1987 by EpAc Software.  All Rights Reserved.
  8. **
  9. **  History:    05-Jan-87       Original Version (1.0)
  10. **        07-Feb-87    Added conditional compilation for autoname.
  11. */
  12.  
  13. #include   <libraries/dos.h>
  14. #include   <libraries/dosextens.h>
  15. #include   <libraries/filehandler.h>
  16. #include   <exec/exec.h>
  17.  
  18. #include   "pipelists.h"
  19. #include   "pipename.h"
  20. #include   "pipebuf.h"
  21. #include   "pipecreate.h"
  22. #include   "pipesched.h"
  23. #include   "pipe-handler.h"
  24.  
  25.  
  26.  
  27. /*---------------------------------------------------------------------------
  28. ** pipename.c
  29. ** ----------
  30. ** This module contains functions related to the parsing of the pipe names.
  31. **
  32. ** Visible Functions
  33. ** -----------------
  34. **    int   ParsePipeName (Bname, nmp, sizep, tapnmp)
  35. **    void  BSTRtoCstr    (BSTRp, str, maxsize)
  36. **    void  CstrtoBSTR    (str, BSTRp, maxsize)
  37. **    int   inrange       (x, lower, upper)
  38. **    char  uppercase     (c)
  39. **    char  *findchar     (str, ch)
  40. **    void  l_strcpy      (to, from)
  41. **    char  *strdiff      (str1, str2)
  42. **    char  *get_autoname (newflag)     (if AUTONAME is true)
  43. **
  44. ** Macros (in pipename.h)
  45. ** ----------------------
  46. **    isnumeral (c)
  47. **
  48. ** Local Functions
  49. ** ---------------
  50. **    int  ParseNum (str, nump)
  51. */
  52.  
  53.  
  54.  
  55. /*---------------------------------------------------------------------------
  56. ** ParsePipeName() parses the string "Bname" into three parts: a pipe name,
  57. ** a size specification and a tap name.  (Bname must be the byte address of a
  58. ** BSTR, i.e., a string whose first byte is its length.)  The three parts are
  59. ** separated by the character PIPE_SPEC_CHAR (defined in pipename.h).
  60. ** Assuming that PIPE_SPEC_CHAR is '/', and that '[]' are metacharacters
  61. ** which enclose optional parts, the syntax for Bname is [D:][p][/n][/[t]].
  62. ** Here, "D" represents a device name, "p" represents a pipe name,
  63. ** "n" represents a number and "t" represents a tap name.
  64. **      ParsePipeName() returns nonzero iff "Bname" conforms to the syntax
  65. ** and the following restrictions.
  66. **      "D:" represents a device name.  If it occurs, it is ignored.  Notice
  67. ** that tap names which contain a ":" force a device name to be specified for
  68. ** the pipe.  Otherwise, everything up to and including the ":" in the tap
  69. ** name will be ignored.
  70. **      *nmp returns pointing to a copy of "p", even if it is empty.  Default
  71. ** pipe names are handled by calling get_autoname().  (This is done by
  72. ** OpenPipe() if *nmp returns empty.)
  73. **      "n" must begin with a digit.  If "n" begins with "0x", it is parsed
  74. ** as a hexadecimal number.  If it begins with "0" but not "0x", it is parsed
  75. ** as an octal number.  Otherwise, it is parsed as a decimal number.  If the
  76. ** size specifier ("/t" above) is not given, *sizep is set to DEFAULT_PIPELEN.
  77. **     If the compile-time flag CON_TAP_ONLY is set, "t" may only be a "CON:"
  78. ** file specifier, such as "CON:10/10/400/120/TapWindow".  If CON_TAP_ONLY is
  79. ** not set, string is accepted.  If "t" is empty (but the PIPE_SPEC_CHAR was
  80. ** given), then a defualt tap name is formed by appending "p" to
  81. ** DEFAULT_TAPNAME_PREFIX.  If the tap name specifier ("/[t]" above) is not
  82. ** given, *tapnmp is set to NULL.
  83. */
  84.  
  85. static char  default_tapname_prefix[]  =  DEFAULT_TAPNAME_PREFIX;
  86. static char  namebuf[sizeof (default_tapname_prefix) + PIPENAMELEN];
  87.  
  88. int  ParsePipeName (Bname, nmp, sizep, tapnmp)
  89.  
  90. BYTE   *Bname;       /* reference to BSTR name sent to handler */
  91. char   **nmp;        /* reference to pipe name pointer */
  92. ULONG  *sizep;       /* size longword pointer */
  93. char   **tapnmp;     /* reference to tap name pointer, returns NULL if none */
  94.  
  95. { char  *cp;
  96.   int   ParseNum();
  97.  
  98.  
  99.   l_strcpy (namebuf, default_tapname_prefix);
  100.  
  101.   *nmp=    namebuf + (sizeof (default_tapname_prefix) - 1);
  102.   *sizep=  DEFAULT_PIPELEN;
  103.   *tapnmp= NULL;
  104.  
  105.   BSTRtoCstr (Bname, *nmp, PIPENAMELEN);
  106.  
  107.   if (*(cp= findchar (*nmp, ':')) == ':')
  108.     l_strcpy (*nmp, ++cp);     /* get rid of "devname:" prefix */
  109.  
  110.   if ( *(cp= findchar (*nmp, PIPE_SPEC_CHAR)) )     /* true if not '\0' */
  111.     { *(cp++)= '\0';     /* terminate pipe name */
  112.  
  113.       if (isnumeral (*cp))
  114.         { if ( (! ParseNum (cp, sizep)) || (*sizep <= 0) )
  115.             return FALSE;
  116.  
  117.           if ( *(cp= findchar (cp, PIPE_SPEC_CHAR)) == '\0' )
  118.             return TRUE;     /* no tap name, but successful anyway */
  119.  
  120.           ++cp;     /* skip separator */
  121.         }
  122.  
  123.       if ( *(*tapnmp= cp) == '\0' )     /* first character of tap name */
  124.         *tapnmp= namebuf;     /* use default prefix prepended to pipe name */
  125. #if CON_TAP_ONLY
  126.       else
  127.         { if ( *(strdiff ("CON:", *tapnmp)) )     /* true if not '\0' */
  128.             return FALSE;     /* only CON: . . . allowed */
  129.         }
  130. #endif CON_TAP_ONLY
  131.     }
  132.  
  133.   return TRUE;
  134. }
  135.  
  136.  
  137.  
  138. /*---------------------------------------------------------------------------
  139. ** BSTRtoCstr() converts the BSTR pointed to by "BSTRp" (a byte address) to
  140. ** a null-terminated string, storing the result in the locations pointed to
  141. ** by "str".  At most "maxsize" bytes will be stored.
  142. */
  143.  
  144. void  BSTRtoCstr (BSTRp, str, maxsize)
  145.  
  146. register BYTE  *BSTRp;
  147. register char  *str;
  148. unsigned       maxsize;
  149.  
  150. { register int   i;
  151.   register int   limit;
  152.  
  153.  
  154.   if ((limit= *(BSTRp++)) > ((int) maxsize - 1))     /* leave room for '\0' */
  155.     limit= (int) maxsize - 1;
  156.  
  157.   for (i= 0; i < limit; ++i)
  158.     *(str++)= *(BSTRp++);
  159.  
  160.   *str= '\0';
  161. }
  162.  
  163.  
  164.  
  165. /*---------------------------------------------------------------------------
  166. ** CstrtoBSTR() converts the null-terminated string pointed to by "str" to
  167. ** a BSTR located at the byte address "BSTRp".  At most "maxsize" bytes will
  168. ** be stored.
  169. */
  170.  
  171. void  CstrtoBSTR (str, BSTRp, maxsize)
  172.  
  173. register char  *str;
  174. BYTE           *BSTRp;
  175. unsigned       maxsize;
  176.  
  177. { register char  *bp;
  178.   register int   i, limit;
  179.  
  180.  
  181.   bp= BSTRp + 1;
  182.  
  183.   limit= maxsize - 1;
  184.  
  185.   for (i= 0; i < limit; ++i)
  186.     if ( (*(bp++)= *(str++)) == '\0' )
  187.       break;
  188.  
  189.   BSTRp[0]= i;
  190. }
  191.  
  192.  
  193.  
  194. /*---------------------------------------------------------------------------
  195. ** inrange() returns nonzero iff x is in the range [lower, upper].
  196. ** uppercase() returns the uppercase version of the ASCII character sent.
  197. ** These are not implemented as macros to avoid hard-to-find bugs like
  198. ** uppercase(c++), where the side-effect occurs more than once.
  199. */
  200.  
  201. int  inrange (x, lower, upper)
  202.  
  203. register int  x;
  204. register int  lower;
  205. register int  upper;
  206.  
  207. { return  ((x >= lower) && (x <= upper));
  208. }
  209.  
  210.  
  211. char  uppercase (c)
  212.  
  213. register char  c;
  214.  
  215. { return  (char) (inrange (c, 'a', 'z') ? (c + ('A' - 'a')) : c);
  216. }
  217.  
  218.  
  219.  
  220. /*---------------------------------------------------------------------------
  221. ** The null-terminated string "str" is scanned for the character "ch".  If
  222. ** found, a pointer to its first occurrence in "str" is returned.  Otherwise,
  223. ** a pointer to the terminating '\0' in "str" is returned.
  224. */
  225.  
  226. char  *findchar (str, ch)
  227.  
  228. register char  *str;
  229. register char  ch;
  230.  
  231. { while ((*str != '\0') && (*str != ch))
  232.     ++str;
  233.  
  234.   return str;     /* return position of ch, or end if not found */
  235. }
  236.  
  237.  
  238.  
  239. /*---------------------------------------------------------------------------
  240. ** This is just like strcpy().  Its is defined here to avoid including other
  241. ** libraries.
  242. */
  243.  
  244. void  l_strcpy (to, from)
  245.  
  246. register char  *to;
  247. register char  *from;
  248.  
  249. {
  250. STRCPYLOOP:
  251.   if (*(to++)= *(from++))
  252.     goto STRCPYLOOP;
  253. }
  254.  
  255.  
  256.  
  257. /*---------------------------------------------------------------------------
  258. ** strdiff() returns a pointer to the first difference in the two null-
  259. ** terminated strings "str1" and "str2".  If no differnce is found, or if
  260. ** "str1" is shorter than "str2", then a pointer to '\0' is returned.
  261. ** The returned pointer is to a character in "str1".
  262. */
  263.  
  264. char  *strdiff (str1, str2)
  265.  
  266. register char  *str1;
  267. register char  *str2;
  268.  
  269. { while ( *str1 && (uppercase (*str1) == uppercase (*str2)) )
  270.     { ++str1;
  271.       ++str2;
  272.     }
  273.  
  274.   return str1;     /* return position of first difference, or end of str1 */
  275. }
  276.  
  277.  
  278.  
  279. /*---------------------------------------------------------------------------
  280. ** get_autoname() returns a pointer to "autoname".  If "newflag" is nonzero,
  281. ** autoname is first updated so that it does not conflict with any existing
  282. ** pipe name.  This is done by looking for a block of ASCII digits in
  283. ** "autoname", and incrementing their effective value.  "autoname" MUST
  284. ** contain such a block of digits.
  285. */
  286.  
  287. #if AUTONAME
  288.  
  289. static char  autoname[]  =  AUTONAME_INIT;
  290.  
  291. char  *get_autoname (newflag)
  292.  
  293. BYTE  newflag;
  294.  
  295. { char      *cp, *cpc;
  296.   PIPEDATA  *FindPipe();
  297.  
  298.  
  299.   if (newflag)     /* then create a new unique pipe name */
  300.     { cp= findchar (autoname, '\0');
  301.  
  302.       while (! isnumeral (*cp))     /* find last numeral */
  303.         --cp;
  304.  
  305.       do
  306.         { ++(*cp);     /* "increment" name */
  307.  
  308.           for (cpc= cp; (! isnumeral (*cpc)); )     /* ripple carry */
  309.             { *(cpc--)= '0';
  310.  
  311.               if (! isnumeral (*cpc))
  312.                 break;     /* no more digits */
  313.  
  314.               ++(*cpc);
  315.             }
  316.         }
  317.       while (FindPipe (autoname) != NULL);     /* repeat until name is unique */
  318.     }
  319.  
  320.  
  321.   return  autoname;
  322. }
  323.  
  324. #endif AUTONAME
  325.  
  326.  
  327.  
  328. /*---------------------------------------------------------------------------
  329. ** ParseNum() parses the null-terminated string pointed to by "str" into a
  330. ** number, and stores its value in *nump.  ParseNum() returns nonzero iff
  331. ** successful.  Both '\0' and PIPE_SPEC_CHAR are acceptable terminators for
  332. ** the number.
  333. **      If the number begins with "0x", it is interpreted as hexadecimal.
  334. ** If it begins with "0" but not "0x", it is interpreted as octal.
  335. ** Otherwise, it is interpreted as decimal.
  336. */
  337.  
  338. static int  ParseNum (str, nump)
  339.  
  340. char   *str;
  341. ULONG  *nump;
  342.  
  343. { int   radix    =  10;
  344.   char  *digits  =  "0123456789ABCDEF";
  345.   LONG  value;
  346.  
  347.  
  348.   if ((*str == '0') && (uppercase (*(str + 1)) == 'X'))
  349.     { radix= 16;
  350.       str += 2;
  351.     }
  352.   else if (*str == '0')
  353.     { radix= 8;
  354.       ++str;
  355.     }
  356.  
  357.   for (*nump= 0; TRUE; ++str)
  358.     { value= (LONG) findchar (digits, uppercase (*str)) - (LONG) digits;
  359.  
  360.       if (! inrange (value, 0, (radix - 1)))
  361.         break;
  362.  
  363.       if (*nump > ((MAX_PIPELEN - value) / radix))
  364.         return FALSE;
  365.  
  366.       *nump *= radix;
  367.       *nump += value;
  368.     }
  369.  
  370.  
  371.   return  ( (*str == PIPE_SPEC_CHAR) || (*str == '\0') );
  372. }
  373.